package com.zhz.common.tool.sms.aliyun;

import cn.hutool.json.JSONUtil;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.*;
import com.aliyun.teaopenapi.models.Config;
import com.zhz.common.tool.sms.SmsSender;

import java.util.Map;
import java.util.Objects;

/**
 * 阿里云短信平台 v2.0
 * https://next.api.aliyun.com/api-tools/sdk/Dysmsapi?version=2017-05-25&language=java-tea&tab=primer-doc
 *
 * @author zhouhengzhe
 */
public class AliyunSmsSender implements SmsSender {

    private final String accessKeyId;
    private final String accessKeySecret;

    private final String endpoint;

    private Client client;

    public AliyunSmsSender(String accessKeyId, String accessKeySecret, String endpoint) {
        this.accessKeyId = accessKeyId;
        this.accessKeySecret = accessKeySecret;
        this.endpoint = endpoint;
        try {
            buildClient();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void buildClient() throws Exception {
        Config config = new Config().setAccessKeyId(accessKeyId).setAccessKeySecret(accessKeySecret);
        // 访问的域名
        config.endpoint = this.endpoint;
        this.client = new Client(config);
    }

    /**
     * 验证码类型短信，建议使用接口SendSms单独发送
     * 发送1对1短信(也可以多个手机号，但是会被当成群发短信)
     *
     * @param phoneNumber    手机号
     * @param template       模板(代码或内容)
     * @param templateParams 参数
     * @param signName       签名
     * @return
     */
    @Override
    public boolean sendSingle(String phoneNumber, String template, Map<String, String> templateParams, String signName) {
        try {
            //组装请求对象-具体描述见控制台-文档部分内容
            SendSmsRequest request = new SendSmsRequest();
            //必填:待发送手机号
            request.setPhoneNumbers(phoneNumber);
            //必填:短信签名-可在短信控制台中找到
            request.setSignName(signName);
            //必填:短信模板-可在短信控制台中找到
            request.setTemplateCode(template);
            //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
            //{"name":"张三","number":"1390000****"}
            request.setTemplateParam(JSONUtil.toJsonStr(templateParams));
            //hint 此处可能会抛出异常，注意catch
            SendSmsResponse sendSmsResponse = client.sendSms(request);
            if (sendSmsResponse.getStatusCode() == 200) {
                SendSmsResponseBody body = sendSmsResponse.getBody();
                if ("OK".equals(body.getCode())) {
                    return true;
                }
            }
        } catch (Exception error) {
        }

        return false;
    }

    /**
     * @param phoneNumberJson 多个手机号，json显示
     *                        国内短信：+/+86/0086/86或无任何前缀的11位手机号码，例如1590000****。
     *                        国际/港澳台消息：国际区号+号码，例如852000012****。
     * @param templateCode    模板(代码或内容),必须是已添加、并通过审核的短信签名；且短信签名的个数必须与手机号码的个数相同、内容一一对应。
     * @param templateParams  参数
     *                        如果JSON中需要带换行符，请参照标准的JSON协议处理；且模板变量值的个数必须与手机号码、签名的个数相同、
     *                        内容一一对应，表示向指定手机号码中发对应签名的短信，且短信模板中的变量参数替换为对应的值
     * @param signNameJson    短信签名名称。
     *                        必须是已添加、并通过审核的短信签名；且短信签名的个数必须与手机号码的个数相同、内容一一对应。
     * @return
     */
    @Override
    public boolean sendBatch(String phoneNumberJson, String templateCode, String templateParams, String signNameJson) {
        try {
            //组装请求对象-具体描述见控制台-文档部分内容
            SendBatchSmsRequest request = new SendBatchSmsRequest();
            //必填:待发送手机号
            request.setPhoneNumberJson(phoneNumberJson);
            //必填:短信签名-可在短信控制台中找到
            request.setSignNameJson(signNameJson);
            //必填:短信模板-可在短信控制台中找到
            request.setTemplateCode(templateCode);
            //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
            //{"name":"张三","number":"1390000****"}
            request.setTemplateParamJson(templateParams);
            //hint 此处可能会抛出异常，注意catch
            SendBatchSmsResponse sendBatchSmsResponse = client.sendBatchSms(request);
            if (sendBatchSmsResponse.getStatusCode() == 200) {
                SendBatchSmsResponseBody responseBody = sendBatchSmsResponse.getBody();
                if ("OK".equals(responseBody.getCode())) {
                    return true;
                }
            }
        } catch (Exception error) {
            throw new RuntimeException("发送短信失败", error);
        }
        return false;
    }

    /**
     * 查询短信发送统计信息
     * <a href="https://help.aliyun.com/document_detail/419276.html?spm=a2c4g.419277.0.0.7e0e7d3fMlkLHt">...</a>
     *
     * @param querySendStatisticsRequest 查询条件
     * @return 查询结果
     */
    @Override
    public QuerySendStatisticsResponse querySendStatistics(QuerySendStatisticsRequest querySendStatisticsRequest) {
        try {
            QuerySendStatisticsResponse querySendStatisticsResponse = client.querySendStatistics(querySendStatisticsRequest);
            if (querySendStatisticsResponse.getStatusCode() != 200) {
                throw new RuntimeException("查询短信发送统计信息失败，异常码信息为" + querySendStatisticsResponse.getStatusCode());
            }
            if (Objects.isNull(querySendStatisticsResponse.getBody()) || !"OK".equals(querySendStatisticsResponse.getBody().getCode())) {
                throw new RuntimeException("查询短信发送统计信息失败，异常信息为" + querySendStatisticsResponse.getBody().getMessage());
            }
            return querySendStatisticsResponse;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * 查询短信发送详情
     * <a href="https://help.aliyun.com/document_detail/419277.html?spm=a2c4g.419276.0.0.59ce5076BWndpH">...</a>
     *
     * @param querySendDetailsRequest 查询条件
     * @return 查询结果
     */
    @Override
    public QuerySendDetailsResponse querySendDetails(QuerySendDetailsRequest querySendDetailsRequest) {
        try {
            QuerySendDetailsResponse querySendDetailsResponse = client.querySendDetails(querySendDetailsRequest);
            if (querySendDetailsResponse.getStatusCode() != 200) {
                throw new RuntimeException("查询短信发送统计信息失败，异常码信息为" + querySendDetailsResponse.getStatusCode());
            }
            if (Objects.isNull(querySendDetailsResponse.getBody()) || !"OK".equals(querySendDetailsResponse.getBody().getCode())) {
                throw new RuntimeException("查询短信发送统计信息失败，异常信息为" + querySendDetailsResponse.getBody().getMessage());
            }
            return querySendDetailsResponse;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * 申请短信模板
     * <a href="https://help.aliyun.com/document_detail/419285.html?spm=a2c4g.419276.0.0.336e1c33PBj94Z">...</a>
     *
     * @param addSmsTemplateRequest 模板信息
     * @return 模板信息
     */
    @Override
    public AddSmsTemplateResponse addSmsTemplate(AddSmsTemplateRequest addSmsTemplateRequest) {
        try {
            AddSmsTemplateResponse addSmsTemplateResponse = client.addSmsTemplate(addSmsTemplateRequest);
            if (addSmsTemplateResponse.getStatusCode() != 200) {
                throw new RuntimeException("查询短信发送统计信息失败，异常码信息为" + addSmsTemplateResponse.getStatusCode());
            }
            if (Objects.isNull(addSmsTemplateResponse.getBody()) || !"OK".equals(addSmsTemplateResponse.getBody().getCode())) {
                throw new RuntimeException("查询短信发送统计信息失败，异常信息为" + addSmsTemplateResponse.getBody().getMessage());
            }
            return addSmsTemplateResponse;
        } catch (Exception e) {
            throw new RuntimeException("查询短信发送详情失败", e);
        }
    }

    /**
     * 查询短信模板列表
     * <a href="https://help.aliyun.com/document_detail/419288.html?spm=a2c4g.419287.0.0.201a31f3CDgK2g">...</a>
     *
     * @param querySmsTemplateListRequest 模板信息
     * @return 模板信息
     */
    @Override
    public QuerySmsTemplateListResponse querySmsTemplateList(QuerySmsTemplateListRequest querySmsTemplateListRequest){
        try {
            QuerySmsTemplateListResponse querySmsTemplateListResponse = client.querySmsTemplateList(querySmsTemplateListRequest);
            if (querySmsTemplateListResponse.getStatusCode() != 200) {
                throw new RuntimeException("查询短信发送统计信息失败，异常码信息为" + querySmsTemplateListResponse.getStatusCode());
            }
            if (Objects.isNull(querySmsTemplateListResponse.getBody()) || !"OK".equals(querySmsTemplateListResponse.getBody().getCode())) {
                throw new RuntimeException("查询短信发送统计信息失败，异常信息为" + querySmsTemplateListResponse.getBody().getMessage());
            }
            return querySmsTemplateListResponse;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
